using System;
using System.Collections.Generic;
using System.Reflection;
using Ease.EaseNode.Runtime;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

namespace Ease.EaseNode.Editor.NodeView
{
    /// <summary>
    /// 
    /// </summary>
    public abstract class BaseEaseEditorWindow : EditorWindow, IEaseEditorWindow
    {
        public BaseEaseChartView EaseChartView { get; set; }

        public IUpdateSelection UpdateSelection { get; set; }

        public INodeDataManager DataManager { get; set; }

        protected Dictionary<Type, Type> dicData2Node = new Dictionary<Type, Type>();

        protected virtual void OnEnable()
        {
            //Debug.LogError("OnEnable");
            EditorApplication.playModeStateChanged -= OnPlayModeChange;
            EditorApplication.playModeStateChanged += OnPlayModeChange;
            
            OnPrepareData();
        }

        protected virtual void Update()
        {
           
        }

        protected virtual void OnDisable()
        {
            //Debug.LogError("OnDisable");
            EaseChartView?.OnDisable();
        }

        private void OnDestroy()
        {
            //Debug.LogError("OnDestroy");
            ResetChartView();
        }

        public virtual void OnUpdateSelection(BaseEaseNode easeNode)
        {
            UpdateSelection?.OnUpdateSelection(easeNode);
        }

        protected void InitChartView()
        {
            EaseChartView.OnGetWindowMousePosition += OnGetWindowMousePos;
            EaseChartView.OnCreateAllNodes += OnCreateAllNodes;
            EaseChartView.OnCreateNode += OnCreateNode;
            EaseChartView.OnNodeSelected += OnUpdateSelection;
            EaseChartView.OnRemoveNode += OnRemoveNode;
        }

        private void ResetChartView()
        {
            if (EaseChartView == null)
                return;
            EaseChartView.OnDisable();
            EaseChartView.OnGetWindowMousePosition -= OnGetWindowMousePos;
            EaseChartView.OnCreateAllNodes -= OnCreateAllNodes;
            EaseChartView.OnCreateNode -= OnCreateNode;
            EaseChartView.OnNodeSelected -= OnUpdateSelection;
            EaseChartView.OnRemoveNode -= OnRemoveNode;
        }

        private Vector2 OnGetWindowMousePos(Vector2 screenMousePosition)
        {
            //获取鼠标位置
            var windowRoot = rootVisualElement;
            var windowMousePosition = windowRoot.ChangeCoordinatesTo(windowRoot.parent,
                screenMousePosition - position.position);
            return windowMousePosition;
        }

        protected virtual void OnCreateAllNodes(Action<IEaseNodeDataState> callback)
        {
            DataManager?.PrepareAllDataState(callback);
        }

        protected virtual BaseEaseNode OnCreateNode(Type dataType, IEaseNodeDataState state)
        {
            if (dicData2Node.TryGetValue(dataType, out var nodeType))
            {
                return OnCreateNode(nodeType, dataType, state);
            }

            return null;
        }

        private BaseEaseNode OnCreateNode(Type nodeType, Type dataType, IEaseNodeDataState state)
        {
            ConstructorInfo constructor = nodeType.GetConstructor(new[] { typeof(IEaseNodeDataState) });
            if (constructor != null)
            {
                var param1 = state;
                if (state == null)
                    param1 = DataManager.AddNewData(dataType);
                return constructor.Invoke(new object[] { param1 }) as BaseEaseNode;
            }

            return null;
        }

        protected virtual void OnRemoveNode(BaseEaseNode easeNode)
        {
            if (easeNode != null)
                DataManager.RemoveOneData(easeNode.State.Key);
        }

        protected abstract void OnPrepareData();

        protected virtual void OnPlayModeChange(PlayModeStateChange stateChange)
        {
            if (stateChange == PlayModeStateChange.EnteredEditMode)
            {
                StateManager.Reset();
            }
        }
    }
}